#ifndef _GSUPPLYLINKPROBLEM_H_
#define _GSUPPLYLINKPROBLEM_H_

using namespace std ;

#include <iostream>
#include <vector>
#include <assert.h>

#include "gjobData.h"
#include "gsupplyLinkTransporter.h"
#include "gsupplyLinkSolution.h"

using namespace std ;

#define BP_LSDSP_CLASS_A 1


/**
 * Supply link problem for which the production batch
 * sequence is the same as the transportation batch
 * sequence (ECC09)
 *
 * @author me
 *
 */
class GSupplyLinkSolution ;
class GSupplyLinkProblem {

    private:
        /**
         * Number of product to produce and deliver to the client
         */
        int np ;

        /**
         * customer holding cost per unit of time and per part
         */
        vector<GJobData> jobData ;


        // Size of the vector NOT initialized by constructor

        /**
         * List of the transporters for the supplylink
         */
        vector<GSupplyLinkTransporter> transporters ;

        vector<int> jobPermutation ;

	bool customerHoldingCostsIdentical ;
	bool dueDatesIdentical ;
	int problemClass ;

    public:
        /**
         * @param np_ nbr product
         */
        GSupplyLinkProblem():np(0){initDefaultValues();}
	GSupplyLinkProblem(int np_):np(np_),jobData(np_),jobPermutation(np_){initDefaultValues() ;}
        ~GSupplyLinkProblem() {}

	void initDefaultValues() {
	  customerHoldingCostsIdentical = false ;
	  dueDatesIdentical = false ;
	  problemClass = 0 ;
	}

        // Inlines
        inline const int getNP() const { return np ; }
        inline const int getNbrTransporter() const { return transporters.size() ; }
        inline GSupplyLinkTransporter& getTransporter(int t) { return transporters[t] ; }

        inline double getJobDueDate(int i) const {return jobData[i].getDueDate() ;}
        inline double getJobSize(int i) const {return jobData[i].getSize() ;}
        inline double getJobHoldingCost(int i) const {return jobData[i].getHoldingCost() ;}

	inline int getProblemClass() const { return problemClass ; }

	inline bool isCustomerHoldingCostsIdentical() const {return customerHoldingCostsIdentical ; }
	inline bool isCustomerHoldingCostsZero() const {return customerHoldingCostsIdentical && getJobHoldingCost(0)==0.0 ; }

        // Methods
        void setDimension(int d) ;
        void open(string str, int node) ;

        GSupplyLinkSolution getBestSolutionFromBestSolutionPermuted(GSupplyLinkSolution& bestSolutionPermuted) ;

    friend ostream& operator<< (ostream&, const GSupplyLinkProblem&) ;
} ;

ostream& operator<< (ostream&, const GSupplyLinkProblem&) ;
#endif
